/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

/* eslint-disable react/jsx-no-bind */
import React, { PureComponent } from 'react';
import { Table, Form, Input, Select } from 'antd';
import { debounce, cloneDeep } from 'lodash';
import StandardTable from '@/components/StandardTable';
import styles from './index.less';

const { Option } = Select;
const FormItem = Form.Item;
const EditableContext = React.createContext();

const EditableRow = ({ form, index, ...props }) => (
  <EditableContext.Provider value={form}>
    <tr {...props} />
  </EditableContext.Provider>
);
const EditableFormRow = Form.create()(EditableRow);

// 需要屏蔽密码的品牌
const hidePwdBrands = ['sto'];
// 需要屏蔽三段码的品牌
const hideThirdCodeBrands = ['sto'];

class EditableCell extends PureComponent {
  state = {
    editing: false,
    passed: false,
    errorFields: [],
    hasEdited: false,
  };

  onGetCodeList = (open, value) => {
    const { selectSave } = this.props;
    open && selectSave(value);
  };

  onBlur() {
    const { passed, errorFields, hasEdited } = this.state;
    const { record, handleSave } = this.props;
    const formValues = this.form.getFieldsValue();
    if (!passed && !hasEdited) {
      this.toggleEdit(false);
    }
    if (passed) {
      this.toggleEdit(false);
      hasEdited && handleSave({ ...record, ...formValues, passed, errorFields }, this.props);
    }
  }

  onChange = debounce(
    () => {
      const { record, handleSave } = this.props;
      const { brand } = record || {};
      this.setState({
        hasEdited: true,
      });
      const validateFields = [
        'gun_account_v2',
        'branch_code',
        'gun_account',
        'gun_pwd',
        'gun_pwd_v2',
        'third_code',
      ];

      if (brand == 'ems') {
        validateFields.splice(0, 1);
      }

      this.form.validateFields(validateFields, (error, values) => {
        const errorKeys = error ? Object.keys(error) : [];
        if (
          error &&
          (error.gun_account ||
            error.gun_pwd ||
            error.third_code ||
            error.gun_account_v2 ||
            error.gun_pwd_v2)
        ) {
          this.setState(
            () => ({
              passed: false,
              editing: true,
              errorFields: errorKeys,
            }),
            () => {
              handleSave(
                { ...record, ...values, passed: false, errorFields: errorKeys },
                this.props,
              );
            },
          );
          return;
        }
        if (error && error.branch_code) {
          this.setState(
            () => ({
              passed: true,
              editing: false,
              errorFields: errorKeys,
            }),
            () => {
              handleSave(
                { ...record, ...values, passed: true, errorFields: errorKeys },
                this.props,
              );
            },
          );
          return;
        }
        this.setState({
          passed: true,
          errorFields: [],
        });
      });
    },
    200,
    {
      leading: false,
      trailing: true,
    },
  );

  saveSlect = val => {
    const { passed } = this.state;
    const { record, handleSave } = this.props;
    this.form.setFieldsValue({
      branch_code: val,
    });
    this.form.validateFields((error, values) => {
      const errorKeys = error ? [...Object.keys(error)] : [];
      if (error && error.branch_code) {
        this.setState(
          () => ({
            errorFields: errorKeys,
          }),
          () => {
            handleSave({ ...record, ...values, passed, errorFields: errorKeys }, this.props);
          },
        );
        return;
      }
      this.setState({
        errorFields: [],
        editing: false,
      });
      handleSave({ ...record, ...values, passed, errorFields: errorKeys }, this.props);
    });
  };

  toggleEdit(edit) {
    this.setState({ editing: edit }, () => {
      if (edit) {
        this.input.focus();
      }
    });
  }

  render() {
    const { editing } = this.state;
    const {
      editable,
      selectable,
      dataIndex,
      record,
      handleSave,
      dispatch,
      selectSave,
      placeholder,
      rules,
      branchesList,
      getBranchInfo,
      fakeAccount,
      ...restProps
    } = this.props;
    const brand = record && record.brand;

    const hidePwd = hidePwdBrands.includes(brand) && dataIndex == 'gun_pwd';
    const hideThirdCode = hideThirdCodeBrands.includes(brand) && dataIndex == 'third_code';
    const hidePlaceHolder =
      hideThirdCode &&
      restProps.children[2].props &&
      restProps.children[2].props.children === '请输入三段码';

    const hideYdYt = fakeAccount && ['yd', 'yt'].includes(brand);
    return (
      <td
        ref={node => {
          this.cell = node;
        }}
        className={styles.center}
      >
        {(editable || selectable) && (!hidePwd && !hideThirdCode) ? (
          <EditableContext.Consumer>
            {form => {
              this.form = form;
              return editing || selectable ? (
                <FormItem style={{ margin: 0 }}>
                  {form.getFieldDecorator(dataIndex, {
                    validateTrigger: dataIndex == 'cm_phone ' ? 'onBlur' : '',
                    rules,
                    initialValue: hideYdYt ? undefined : record[dataIndex],
                  })(
                    selectable ? (
                      <Select
                        disabled={hideYdYt}
                        onDropdownVisibleChange={open => this.onGetCodeList(open, record.brand)}
                        onChange={this.saveSlect}
                        style={{ width: 120 }}
                        loading={getBranchInfo}
                        placeholder="请选择网点"
                      >
                        {branchesList.map(item => (
                          <Option key={item} value={item}>
                            {item}
                          </Option>
                        ))}
                      </Select>
                    ) : (
                      <Input
                        disabled={hideYdYt}
                        ref={node => {
                          this.input = node;
                        }}
                        placeholder={placeholder}
                        onChange={this.onChange}
                        onBlur={this.onBlur.bind(this)}
                      />
                    ),
                  )}
                </FormItem>
              ) : (
                <div
                  className="editable-cell-value-wrap"
                  style={{ paddingRight: 24 }}
                  onClick={this.toggleEdit.bind(this, true)}
                >
                  {restProps.children}
                </div>
              );
            }}
          </EditableContext.Consumer>
        ) : hidePwd ? (
          ''
        ) : hidePlaceHolder ? (
          ''
        ) : (
          restProps.children
        )}
      </td>
    );
  }
}

const expandedRowRender = props => {
  const { columns, components, dataSource, record } = props;
  const { brand } = record;
  const tableColumns = cloneDeep(columns).filter(i => i.expandTabledRender);
  const tableList = cloneDeep(dataSource).filter(val => val.brand === brand);
  tableColumns.unshift({ key: '-1', width: 100 }, { key: '-2', width: 160 });
  tableColumns.push({ key: '-3' }, { key: '-4', width: 230 });

  if (['yt', 'ems'].includes(brand)) {
    tableColumns.splice(3, 3);
    tableColumns.push({ key: '-5', colSpan: 0, width: 670 });
  }

  return (
    <Table
      key={`${brand}_expand`}
      className="expand-table"
      size="middle"
      showHeader={false}
      rowClassName={() => 'editable-row'}
      columns={tableColumns}
      components={components}
      dataSource={tableList}
      pagination={false}
      rowKey="brand"
    />
  );
};

class EditableTable extends PureComponent {
  constructor(props) {
    super(props);
    const { columns = [], hasAuthToChangeHtPwd, fakeAccount } = props;
    this.columns = columns.map(col => {
      const { expandTabledRender, dataIndex } = col;
      if (!col.editable && !col.selectable) {
        return {
          render: val => (
            <div className="cell-value-wrap">
              {val || <span className="editable-placeholder">{col.placeholder}</span>}
            </div>
          ),
          ...col,
        };
      }

      return {
        ...col,
        render: (val, record) => {
          const { brand } = record;
          const placeholderMapToBrand = {
            yd: {
              gun_account_v2: '请输入韵镖侠手机号',
              gun_pwd_v2: '请输入韵镖侠密码',
            },
            ht: {
              gun_account_v2: '请输入如来神掌手机号',
              gun_pwd_v2: '请输入如来神掌密码',
            },
            yt: {
              gun_account_v2: '请输入行者手机号',
            },
            ems: {
              gun_account_v2: '请输入邮政设备编码',
            },
          };
          if (expandTabledRender) {
            dataIndex === 'gun_account_v2' &&
              (col.placeholder = placeholderMapToBrand[brand].gun_account_v2);
            dataIndex === 'gun_pwd_v2' &&
              (col.placeholder = placeholderMapToBrand[brand].gun_pwd_v2);
          }
          if (fakeAccount && ['yd', 'yt'].includes(brand)) {
            return col.selectable ? (
              ''
            ) : (
              <span className="editable-placeholder">{col.placeholder}</span>
            );
          }
          return col.selectable
            ? !val
              ? ''
              : val
            : val || <span className="editable-placeholder">{col.placeholder}</span>;
        },
        onCell: record => ({
          ...col,
          record,
          fakeAccount,
          handleSave: this.handleSave,
          dispatch: props.dispatch,
          selectSave: this.selectSave,
          branchesList: this.props.branchesList,
        }),
      };
    });
    if (!hasAuthToChangeHtPwd) {
      hidePwdBrands.push('ht');
    }
  }

  // 回传dataSource给父组件，父组件接受处理完成后给组件设置dataSource属性
  dataSourceChange = (dataSource, ...arg) => {
    const { dataSourceChange } = this.props;
    if (dataSourceChange) {
      dataSourceChange(dataSource || this.initDataSource(), arg[2], arg[1], arg[3]);
    }
  };

  handleSave = (row, { dataIndex }) => {
    const { dataSourceList } = this.props;
    const newData = [...dataSourceList];
    let newDataList = '';
    const index = newData.findIndex(item => row.id === item.id);
    if (JSON.stringify(row) != JSON.stringify(newData[index])) {
      newDataList = row;
    }
    const item = newData[index];
    newData.splice(index, 1, {
      ...item,
      ...row,
    });
    this.dataSourceChange(newData, 'save', dataIndex, newDataList);
  };

  // 网点下拉
  selectSave = value => {
    const { dropdownChange } = this.props;
    dropdownChange(value);
  };

  render() {
    const { dataSourceList = [], expandedRowKeys } = this.props;
    const components = {
      body: {
        row: EditableFormRow,
        cell: EditableCell,
      },
    };
    return (
      <div>
        <StandardTable
          scroll={{ x: 600 }}
          components={components}
          rowKey="brand"
          rowClassName={() => 'editable-row'}
          bordered
          data={{
            list: dataSourceList,
          }}
          columns={this.columns.filter(i => !i.expandTabledRender)}
          pagination={false}
          size="middle"
          align="center"
          defaultExpandedRowKeys={['yd', 'yt', 'ht', 'ems']}
          expandedRowKeys={expandedRowKeys}
          expandIconAsCell={false}
          expandIconColumnIndex={-1}
          expandRowByClick
          expandedRowRender={(record, index, indent, expanded) =>
            expandedRowRender({
              record,
              index,
              indent,
              expanded,
              components,
              columns: this.columns,
              dataSource: dataSourceList,
            })
          }
        />
      </div>
    );
  }
}

export default EditableTable;
